package com.lanchetech.user.service.impl;


import com.alibaba.excel.util.CollectionUtils;
import com.alibaba.fastjson.JSON;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.lanchetech.bean.request.PageReq;
import com.lanchetech.bean.response.BasePageResp;
import com.lanchetech.bean.response.BaseResp;
import com.lanchetech.bean.response.InvoiceApplyResp;
import com.lanchetech.bean.response.ResultData;
import com.lanchetech.bean.util.PageHelpUtil;
import com.lanchetech.bean.vo.InvoiceApplyVO;
import com.lanchetech.bean.vo.InvoiceCountVO;
import com.lanchetech.common.enums.*;
import com.lanchetech.common.util.HttpUtil;
import com.lanchetech.dao.HipoConfigMapper;
import com.lanchetech.dao.InvoiceAccountMapper;
import com.lanchetech.dao.InvoiceApplyMapper;
import com.lanchetech.dao.OrdersMapper;
import com.lanchetech.entity.InvoiceAccount;
import com.lanchetech.entity.InvoiceApply;
import com.lanchetech.entity.Orders;
import com.lanchetech.entity.User;
import com.lanchetech.service.DaoService;
import com.lanchetech.user.service.InvoiceService;
import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

import static com.lanchetech.common.constants.JypConstant.MAX_INVOICE_ACCOUNT_COUNT;

@Service
public class InvoiceServiceImpl implements InvoiceService {

    @Autowired
    InvoiceAccountMapper invoiceAccountMapper;

    @Autowired
    InvoiceApplyMapper invoiceApplyMapper;

    @Autowired
    HipoConfigMapper hipoConfigMapper;

    @Autowired
    OrdersMapper ordersMapper;

    @Autowired
    DaoService daoService;

    // 环境变量
    @Value("${env}")
    private String env;


    @Override
    public BaseResp editInvoiceApply(User user, InvoiceApply invoiceApply) {
        if (invoiceApply.getId() == null) {
            BigDecimal taxRate = daoService.getHipoConfigNumber(HipoConfigEnum.TAX_RATE.getConfig());
            BigDecimal taxCountRate = daoService.getHipoConfigNumber(HipoConfigEnum.TAX_RATE.getConfig()).add(BigDecimal.ONE);

            Orders orders = ordersMapper.selectByPrimaryKey(invoiceApply.getOrderId());
            invoiceApply.setAmount(orders.getTotalPayAmount());
            invoiceApply.setTaxRate(taxRate);
            invoiceApply.setServiceRate(BigDecimal.ZERO);
            invoiceApply.setTax(orders.getTotalPayAmount().subtract(orders.getTotalPayAmount().divide(taxCountRate, 2, BigDecimal.ROUND_HALF_DOWN)));
            invoiceApply.setService(BigDecimal.ZERO);

            // 创建
            invoiceApply.setUserId(user.getId());
            invoiceApply.setType(InvoiceApplyTypeEnum.ORDER.getType());
            invoiceApply.setStatus(InvoiceStatusEnum.PENDING.getStatus());
            invoiceApply.setResultStatus(InvoiceResultStatusEnum.NO.getStatus());
            invoiceApply.setCreatedAt(new Date());
            invoiceApply.setTenantId(orders.getTenantId());
            invoiceApplyMapper.insert(invoiceApply);

            if(orders.getTenantId().equals(1L) || orders.getTenantId().equals(2L)){
                // 申请则立即审核通过
                Map<String, String> params = new HashMap<>();
                params.put("id", invoiceApply.getId().toString());
                params.put("status", InvoiceStatusEnum.DONE.getStatus().toString());
                try {
                    HttpUtil.doJsonPost(JSON.toJSONString(params), "production".equals(env) ? "http://localhost:8084/api/invoice/auditInvoiceApply" : "http://localhost:8082/api/invoice/auditInvoiceApply");
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        } else {
            // 修改
            InvoiceApply result = invoiceApplyMapper.selectByPrimaryKey(invoiceApply.getId());
            if (!result.getUserId().equals(user.getId())) {
                return new BaseResp(ResultCode.FAIL);
            }
            if (InvoiceStatusEnum.DONE.getStatus().equals(result.getStatus())) {
                return new BaseResp(ResultCode.FAIL);
            }
            invoiceApply.setUserId(user.getId());
            invoiceApplyMapper.updateByPrimaryKeySelective(invoiceApply);
        }
        return new BaseResp();
    }

    @Override
    public BaseResp deleteInvoiceAccount(User user, Long id) {
        invoiceAccountMapper.updateDeletedByUserIdAndId(DeletedEnum.DELETED.getStatus(), user.getId(), id);
        return new BaseResp();
    }

    @Override
    public BaseResp editInvoiceAccount(User user, InvoiceAccount invoiceAccount) {
        if (invoiceAccount.getId() == null) {
            // 最多添加20个
            Long count = invoiceAccountMapper.countByUserIdAndDeleted(user.getId(), DeletedEnum.DEFAULT.getStatus());
            if (count >= MAX_INVOICE_ACCOUNT_COUNT) {
                return new BaseResp(ResultCode.INVOICE_ACCOUNT_LIMIT);
            }

            invoiceAccount.setUserId(user.getId());
            invoiceAccount.setUpdatedAt(new Date());
            invoiceAccount.setCreatedAt(new Date());
            invoiceAccount.setDeleted(DeletedEnum.DEFAULT.getStatus());

            // 如果同类型同抬头已存在，则不可以再添加
            if (invoiceAccountMapper.findOneExists(invoiceAccount) != null) {
                return new BaseResp(ResultCode.INVOICE_ACCOUNT_EXISTS);
            }

            invoiceAccountMapper.insert(invoiceAccount);
        } else {
            // 修改，相当于重置
            InvoiceAccount result = invoiceAccountMapper.selectByPrimaryKey(invoiceAccount.getId());
            if (!result.getUserId().equals(user.getId())) {
                return new BaseResp(ResultCode.FAIL);
            }
            invoiceAccount.setUserId(user.getId());
            invoiceAccount.setUpdatedAt(new Date());
            invoiceAccount.setCreatedAt(new Date());
            invoiceAccount.setDeleted(DeletedEnum.DEFAULT.getStatus());
            invoiceAccountMapper.updateByPrimaryKey(invoiceAccount);
        }
        return new BaseResp();
    }

    @Override
    public ResultData<List<InvoiceAccount>> getInvoiceAccountList(User user) {
        return new ResultData<>(invoiceAccountMapper.findAllByUserId(user.getId()));
    }

    @Override
    public ResultData<InvoiceAccount> getInvoiceAccountDetail(User user, Long id) {
        return new ResultData<>(invoiceAccountMapper.findOneByUserIdAndId(user.getId(), id));
    }

    @Override
    public ResultData<InvoiceApplyResp> getInvoiceApplyDetail(User user, Long orderId, Byte type) {
        if (type == null) {
            type = InvoiceApplyTypeEnum.ORDER.getType();
        }

        InvoiceApplyResp resp = new InvoiceApplyResp();
        InvoiceApply invoiceApply = invoiceApplyMapper.findOneByUserIdAndOrderIdAndType(user.getId(), orderId, type);
        if (invoiceApply != null) {
            resp.setInvoiceApply(invoiceApply);
            resp.setInvoiceAccount(invoiceAccountMapper.selectByPrimaryKey(invoiceApply.getInvoiceAccountId()));
            return new ResultData<>(resp);
        }
        return new ResultData<>(null);
    }

    @Override
    public ResultData<BasePageResp<InvoiceApplyVO>> getInvoiceApplyPage(PageReq req) {
        User user = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        req.setUserId(user.getId());

        Page page = PageHelper.startPage(req.getPageNo(), req.getPageSize());
        List<InvoiceApplyVO> list = invoiceApplyMapper.findAllPage(req);
        if (!CollectionUtils.isEmpty(list)) {
            List<InvoiceAccount> accountList = invoiceAccountMapper.findAllByIds(list.stream().map(InvoiceApply::getInvoiceAccountId).collect(Collectors.toList()));
            Map<Long, InvoiceAccount> map = new HashMap<>();
            accountList.stream().forEach(item -> map.put(item.getId(), item));
            list.stream().forEach(item -> {
                item.setInvoiceType(map.get(item.getInvoiceAccountId()).getInvoiceType());
                item.setTitleType(map.get(item.getInvoiceAccountId()).getTitleType());
                item.setTitle(map.get(item.getInvoiceAccountId()).getTitle());
            });
        }
        return PageHelpUtil.buildPage(list, page);
    }

    @Override
    public ResultData<InvoiceCountVO> countInvoice(User user) {
        InvoiceCountVO vo = invoiceApplyMapper.countByUserIdAndStatus(user.getId(), ToggleEnum.ON.getStatus());
        return new ResultData<>(vo);
    }
}